import * as THREE from 'three';
import { OrbitControls } from 'three/addons/controls/OrbitControls.js';
import { CSS2DRenderer, CSS2DObject } from 'three/addons/renderers/CSS2DRenderer.js';
import { CSS3DRenderer, CSS3DObject, CSS3DSprite } from 'three/addons/renderers/CSS3DRenderer.js';

class RendererComparison {
    constructor() {
        this.scene = null;
        this.camera = null;
        this.webglRenderer = null;
        this.css2dRenderer = null;
        this.css3dRenderer = null;
        this.controls = null;
        
        this.objects = [];
        this.labels = [];
        this.currentMode = 'comparison';
        this.animationEnabled = {
            rotation: true,
            float: true
        };
        
        this.init();
        this.createScene();
        this.setupEventListeners();
        this.animate();
    }
    
    init() {
        const canvas = document.getElementById('canvas');
        
        // 创建场景
        this.scene = new THREE.Scene();
        this.scene.background = new THREE.Color(0x0a0a0a);
        
        // 创建相机
        this.camera = new THREE.PerspectiveCamera(
            75,
            window.innerWidth / window.innerHeight,
            0.1,
            1000
        );
        this.camera.position.set(0, 5, 15);
        
        // 创建WebGL渲染器
        this.webglRenderer = new THREE.WebGLRenderer({ 
            canvas: canvas,
            antialias: true,
            alpha: true
        });
        this.webglRenderer.setSize(window.innerWidth, window.innerHeight);
        this.webglRenderer.shadowMap.enabled = true;
        this.webglRenderer.shadowMap.type = THREE.PCFSoftShadowMap;
        this.webglRenderer.setClearColor(0x0a0a0a, 1);
        
        // 创建CSS2D渲染器
        this.css2dRenderer = new CSS2DRenderer();
        this.css2dRenderer.setSize(window.innerWidth, window.innerHeight);
        this.css2dRenderer.domElement.style.position = 'absolute';
        this.css2dRenderer.domElement.style.top = '0px';
        this.css2dRenderer.domElement.style.pointerEvents = 'none';
        this.css2dRenderer.domElement.style.zIndex = '5';
        document.body.appendChild(this.css2dRenderer.domElement);
        
        // 创建CSS3D渲染器
        this.css3dRenderer = new CSS3DRenderer();
        this.css3dRenderer.setSize(window.innerWidth, window.innerHeight);
        this.css3dRenderer.domElement.style.position = 'absolute';
        this.css3dRenderer.domElement.style.top = '0px';
        this.css3dRenderer.domElement.style.pointerEvents = 'none';
        this.css3dRenderer.domElement.style.zIndex = '2';
        document.body.appendChild(this.css3dRenderer.domElement);
        
        // 创建控制器
        this.controls = new OrbitControls(this.camera, this.webglRenderer.domElement);
        this.controls.enableDamping = true;
        this.controls.dampingFactor = 0.05;
        this.controls.minDistance = 5;
        this.controls.maxDistance = 50;
        
        // 添加光源
        this.addLights();
    }
    
    addLights() {
        // 环境光
        const ambientLight = new THREE.AmbientLight(0x404040, 0.6);
        this.scene.add(ambientLight);
        
        // 主方向光
        const directionalLight = new THREE.DirectionalLight(0xffffff, 1);
        directionalLight.position.set(10, 10, 5);
        directionalLight.castShadow = true;
        directionalLight.shadow.mapSize.width = 2048;
        directionalLight.shadow.mapSize.height = 2048;
        directionalLight.shadow.camera.near = 0.5;
        directionalLight.shadow.camera.far = 50;
        directionalLight.shadow.camera.left = -20;
        directionalLight.shadow.camera.right = 20;
        directionalLight.shadow.camera.top = 20;
        directionalLight.shadow.camera.bottom = -20;
        this.scene.add(directionalLight);
        
        // 辅助点光源
        const pointLight1 = new THREE.PointLight(0x667eea, 0.5, 30);
        pointLight1.position.set(-10, 5, -10);
        this.scene.add(pointLight1);
        
        const pointLight2 = new THREE.PointLight(0xff6b6b, 0.5, 30);
        pointLight2.position.set(10, 5, 10);
        this.scene.add(pointLight2);
        
        // 添加地面
        const groundGeometry = new THREE.PlaneGeometry(50, 50);
        const groundMaterial = new THREE.MeshLambertMaterial({ 
            color: 0x1a1a2e,
            transparent: true,
            opacity: 0.8
        });
        const ground = new THREE.Mesh(groundGeometry, groundMaterial);
        ground.rotation.x = -Math.PI / 2;
        ground.position.y = -3;
        ground.receiveShadow = true;
        this.scene.add(ground);
    }
    
    createScene() {
        this.clearScene();
        
        switch(this.currentMode) {
            case 'comparison':
                this.createComparisonScene();
                break;
            case 'css2d':
                this.createCSS2DScene();
                break;
            case 'css3d':
                this.createCSS3DScene();
                break;
            case 'css3dsprite':
                this.createCSS3DSpriteScene();
                break;
            case 'sprite':
                this.createSpriteScene();
                break;
        }
    }
    
    clearScene() {
        // 清除现有对象
        this.objects.forEach(obj => {
            this.scene.remove(obj);
            if (obj.geometry) obj.geometry.dispose();
            if (obj.material) {
                if (Array.isArray(obj.material)) {
                    obj.material.forEach(mat => mat.dispose());
                } else {
                    obj.material.dispose();
                }
            }
        });
        this.objects = [];
        
        // 清除标签
        this.labels.forEach(label => {
            this.scene.remove(label);
        });
        this.labels = [];
    }
    
    createComparisonScene() {
        const positions = [
            { x: -6, z: 0, type: 'css2d', color: 0x667eea },
            { x: -2, z: 0, type: 'css3d', color: 0xff6b6b },
            { x: 2, z: 0, type: 'css3dsprite', color: 0x00ff88 },
            { x: 6, z: 0, type: 'sprite', color: 0xffa500 }
        ];
        
        positions.forEach((pos, index) => {
            // 创建几何体
            const geometry = this.createGeometry();
            const material = new THREE.MeshStandardMaterial({ 
                color: pos.color,
                metalness: 0.3,
                roughness: 0.4
            });
            const mesh = new THREE.Mesh(geometry, material);
            mesh.position.set(pos.x, 0, pos.z);
            mesh.castShadow = true;
            mesh.receiveShadow = true;
            this.scene.add(mesh);
            this.objects.push(mesh);
            
            // 根据类型创建对应的标签
            switch(pos.type) {
                case 'css2d':
                    this.createCSS2DLabel('CSS2D标签', pos.x, 2, pos.z);
                    break;
                case 'css3d':
                    this.createCSS3DElement(pos.x, 2, pos.z);
                    break;
                case 'css3dsprite':
                    this.createCSS3DSpriteLabel('CSS3DSprite', pos.x, 2, pos.z);
                    break;
                case 'sprite':
                    this.createSpriteLabel('Sprite标签', pos.x, 2, pos.z);
                    break;
            }
        });
    }
    
    createCSS2DScene() {
        // 创建单个几何体
        const geometry = this.createGeometry();
        const material = new THREE.MeshStandardMaterial({ 
            color: 0x667eea,
            metalness: 0.3,
            roughness: 0.4
        });
        const mesh = new THREE.Mesh(geometry, material);
        mesh.position.set(0, 0, 0);
        mesh.castShadow = true;
        mesh.receiveShadow = true;
        this.scene.add(mesh);
        this.objects.push(mesh);
        
        // 创建CSS2D标签
        this.createCSS2DLabel('CSS2D Label', 0, 2, 0);
    }
    
    createCSS3DScene() {
        // 创建单个几何体
        const geometry = this.createGeometry();
        const material = new THREE.MeshStandardMaterial({ 
            color: 0xff6b6b,
            metalness: 0.3,
            roughness: 0.4
        });
        const mesh = new THREE.Mesh(geometry, material);
        mesh.position.set(0, 0, 0);
        mesh.castShadow = true;
        mesh.receiveShadow = true;
        this.scene.add(mesh);
        this.objects.push(mesh);
        
        // 创建CSS3D元素
        this.createCSS3DElement(0, 3, 0);
    }
    
    createCSS3DSpriteScene() {
        // 创建单个几何体
        const geometry = this.createGeometry();
        const material = new THREE.MeshStandardMaterial({ 
            color: 0x00ff88,
            metalness: 0.3,
            roughness: 0.4
        });
        const mesh = new THREE.Mesh(geometry, material);
        mesh.position.set(0, 0, 0);
        mesh.castShadow = true;
        mesh.receiveShadow = true;
        this.scene.add(mesh);
        this.objects.push(mesh);
        
        // 创建CSS3DSprite标签
        this.createCSS3DSpriteLabel('CSS3D Sprite', 0, 2, 0);
    }
    
    createSpriteScene() {
        // 创建单个几何体
        const geometry = this.createGeometry();
        const material = new THREE.MeshStandardMaterial({ 
            color: 0xffa500,
            metalness: 0.3,
            roughness: 0.4
        });
        const mesh = new THREE.Mesh(geometry, material);
        mesh.position.set(0, 0, 0);
        mesh.castShadow = true;
        mesh.receiveShadow = true;
        this.scene.add(mesh);
        this.objects.push(mesh);
        
        // 创建Sprite标签
        this.createSpriteLabel('Sprite Label', 0, 2, 0);
    }
    
    createGeometry() {
        const geometryType = document.getElementById('geometryType').value;
        
        switch(geometryType) {
            case 'sphere':
                return new THREE.SphereGeometry(1, 32, 32);
            case 'plane':
                return new THREE.PlaneGeometry(2, 2);
            case 'torus':
                return new THREE.TorusGeometry(1, 0.4, 16, 32);
            default:
                return new THREE.BoxGeometry(2, 2, 2);
        }
    }
    
    createCSS2DLabel(text, x, y, z) {
        const div = document.createElement('div');
        div.className = 'label';
        div.textContent = text;
        
        const css2dObject = new CSS2DObject(div);
        css2dObject.position.set(x, y, z);
        this.scene.add(css2dObject);
        this.labels.push(css2dObject);
    }
    
    createCSS3DElement(x, y, z) {
        const element = document.createElement('div');
        element.className = 'css3d-element';
        element.innerHTML = `
            <h3>CSS3D元素</h3>
            <p>完整的3D变换支持</p>
            <p>位置: (${x.toFixed(1)}, ${y.toFixed(1)}, ${z.toFixed(1)})</p>
        `;
        
        const css3dObject = new CSS3DObject(element);
        css3dObject.position.set(x, y, z);
        css3dObject.scale.set(0.015, 0.015, 0.015);
        this.scene.add(css3dObject);
        this.labels.push(css3dObject);
    }
    
    createCSS3DSpriteLabel(text, x, y, z) {
        const div = document.createElement('div');
        div.className = 'sprite-label';
        div.textContent = text;
        
        const css3dSprite = new CSS3DSprite(div);
        css3dSprite.position.set(x, y, z);
        css3dSprite.scale.set(0.015, 0.015, 0.015);
        this.scene.add(css3dSprite);
        this.labels.push(css3dSprite);
    }
    
    createSpriteLabel(text, x, y, z) {
        // 创建Canvas纹理
        const canvas = document.createElement('canvas');
        const context = canvas.getContext('2d');
        canvas.width = 256;
        canvas.height = 64;
        
        // 绘制背景
        context.fillStyle = 'rgba(255, 165, 0, 0.9)';
        context.fillRect(0, 0, canvas.width, canvas.height);
        
        // 绘制边框
        context.strokeStyle = 'rgba(255, 255, 255, 0.8)';
        context.lineWidth = 2;
        context.strokeRect(0, 0, canvas.width, canvas.height);
        
        // 绘制文字
        context.fillStyle = 'white';
        context.font = 'bold 20px Arial';
        context.textAlign = 'center';
        context.textBaseline = 'middle';
        context.fillText(text, canvas.width / 2, canvas.height / 2);
        
        // 创建纹理和材质
        const texture = new THREE.CanvasTexture(canvas);
        const spriteMaterial = new THREE.SpriteMaterial({ 
            map: texture,
            transparent: true,
            alphaTest: 0.1
        });
        
        // 创建Sprite
        const sprite = new THREE.Sprite(spriteMaterial);
        sprite.position.set(x, y, z);
        sprite.scale.set(2, 0.5, 1);
        this.scene.add(sprite);
        this.labels.push(sprite);
    }
    
    setupEventListeners() {
        // 渲染器类型切换
        document.getElementById('rendererType').addEventListener('change', (e) => {
            this.currentMode = e.target.value;
            this.createScene();
            this.updateInfoPanel();
        });
        
        // 几何体类型切换
        document.getElementById('geometryType').addEventListener('change', () => {
            this.createScene();
        });
        
        // 动画控制
        document.getElementById('enableRotation').addEventListener('change', (e) => {
            this.animationEnabled.rotation = e.target.checked;
        });
        
        document.getElementById('enableFloat').addEventListener('change', (e) => {
            this.animationEnabled.float = e.target.checked;
        });
        
        // 窗口大小调整
        window.addEventListener('resize', () => {
            this.onWindowResize();
        });
        
        // 初始化信息面板
        this.updateInfoPanel();
    }
    
    updateInfoPanel() {
        const sections = document.querySelectorAll('.renderer-section');
        sections.forEach(section => section.style.display = 'none');
        
        const title = document.getElementById('renderer-title');
        
        switch(this.currentMode) {
            case 'comparison':
                title.textContent = '四种渲染器对比';
                sections.forEach(section => section.style.display = 'block');
                break;
            case 'css2d':
                title.textContent = 'CSS2DRenderer 详解';
                document.getElementById('css2d-section').style.display = 'block';
                break;
            case 'css3d':
                title.textContent = 'CSS3DRenderer 详解';
                document.getElementById('css3d-section').style.display = 'block';
                break;
            case 'css3dsprite':
                title.textContent = 'CSS3DSprite 详解';
                document.getElementById('css3dsprite-section').style.display = 'block';
                break;
            case 'sprite':
                title.textContent = 'Sprite 详解';
                document.getElementById('sprite-section').style.display = 'block';
                break;
        }
    }
    
    onWindowResize() {
        this.camera.aspect = window.innerWidth / window.innerHeight;
        this.camera.updateProjectionMatrix();
        
        this.webglRenderer.setSize(window.innerWidth, window.innerHeight);
        this.css2dRenderer.setSize(window.innerWidth, window.innerHeight);
        this.css3dRenderer.setSize(window.innerWidth, window.innerHeight);
    }
    
    animate() {
        requestAnimationFrame(() => this.animate());
        
        const time = Date.now() * 0.001;
        
        // 旋转动画
        if (this.animationEnabled.rotation) {
            this.objects.forEach((obj, index) => {
                obj.rotation.y = time + index * 0.5;
                obj.rotation.x = Math.sin(time + index) * 0.2;
            });
        }
        
        // 浮动动画
        if (this.animationEnabled.float) {
            this.objects.forEach((obj, index) => {
                const originalY = 0;
                obj.position.y = originalY + Math.sin(time * 2 + index) * 0.5;
            });
            
            this.labels.forEach((label, index) => {
                if (label.position) {
                    const originalY = this.currentMode === 'sprite' ? 
                        (this.objects[index] ? this.objects[index].position.y + 1 : 2) : 2;
                    label.position.y = originalY + Math.sin(time * 2 + index) * 0.3;
                }
            });
        }
        
        // 更新控制器
        this.controls.update();
        
        // 渲染场景
        this.webglRenderer.render(this.scene, this.camera);
        this.css2dRenderer.render(this.scene, this.camera);
        this.css3dRenderer.render(this.scene, this.camera);
    }
}

// 初始化应用
let app;
window.addEventListener('DOMContentLoaded', () => {
    app = new RendererComparison();
});

export { RendererComparison };